package com.jorado.core.utility;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.NumberFormat;
import java.text.ParseException;

/*
 * Created by len.zhang on 2018/4/2.
 * 基础数据转换
 */
public final class ConvertUtils {

    private ConvertUtils() {

    }

    public static String toString(final Object obj) {
        if (obj != null) {
            return obj.toString();
        }
        return null;
    }

    public static String toString(final Object obj, String defaultValue) {
        String answer = toString(obj);
        if (answer == null) {
            answer = defaultValue;
        }
        return answer;
    }

    public static Number toNumber(final Object obj) {
        if (obj != null) {
            if (obj instanceof Number) {
                return (Number) obj;
            } else if (obj instanceof Boolean) {
                Boolean flag = (Boolean) obj;
                return flag ? 1 : 0;
            } else if (obj instanceof String) {
                try {
                    String text = (String) obj;
                    return NumberFormat.getInstance().parse(text);
                } catch (ParseException e) {
                    // ignore exception
                }
            }
        }
        return null;
    }

    public static Number toNumber(final Object obj, Number defaultValue) {
        Number answer = toNumber(obj);
        if (answer == null) {
            answer = defaultValue;
        }
        return answer;
    }

    public static Boolean toBoolean(final Object obj) {
        if (obj != null) {
            if (obj instanceof Boolean) {
                return (Boolean) obj;
            } else if (obj instanceof String) {
                return Boolean.valueOf((String) obj) || obj.toString().equals("1");
            } else if (obj instanceof Number) {
                Number n = (Number) obj;
                return (n.intValue() != 0) ? Boolean.TRUE : Boolean.FALSE;
            }
        }
        return null;
    }

    public static Boolean toBoolean(final Object obj, Boolean defaultValue) {
        Boolean answer = toBoolean(obj);
        if (answer == null) {
            answer = defaultValue;
        }
        return answer;
    }

    public static boolean toBooleanValue(final Object obj) {
        Boolean booleanObject = toBoolean(obj);
        if (booleanObject == null) {
            return false;
        }
        return booleanObject.booleanValue();
    }

    public static boolean toBooleanValue(final Object obj, boolean defaultValue) {
        Boolean booleanObject = toBoolean(obj);
        if (booleanObject == null) {
            return defaultValue;
        }
        return booleanObject.booleanValue();
    }

    public static Byte toByte(final Object obj) {
        Number answer = toNumber(obj);
        if (answer == null) {
            return null;
        } else if (answer instanceof Byte) {
            return (Byte) answer;
        }
        return Byte.valueOf(answer.byteValue());
    }

    public static Byte toByte(final Object obj, Byte defaultValue) {
        Byte answer = toByte(obj);
        if (answer == null) {
            answer = defaultValue;
        }
        return answer;
    }

    public static byte toByteValue(final Object obj) {
        Byte byteObject = toByte(obj);
        if (byteObject == null) {
            return 0;
        }
        return byteObject.byteValue();
    }

    public static byte toByteValue(final Object obj, byte defaultValue) {
        Byte byteObject = toByte(obj);
        if (byteObject == null) {
            return defaultValue;
        }
        return byteObject.byteValue();
    }

    public static Short toShort(final Object obj) {
        Number answer = toNumber(obj);
        if (answer == null) {
            return null;
        } else if (answer instanceof Short) {
            return (Short) answer;
        }
        return Short.valueOf(answer.shortValue());
    }

    public static Short toShort(final Object obj, Short defaultValue) {
        Short answer = toShort(obj);
        if (answer == null) {
            answer = defaultValue;
        }
        return answer;
    }

    public static short toShortValue(final Object obj) {
        Short shortObject = toShort(obj);
        if (shortObject == null) {
            return 0;
        }
        return shortObject.shortValue();
    }

    public static short toShortValue(final Object obj, short defaultValue) {
        Short shortObject = toShort(obj);
        if (shortObject == null) {
            return defaultValue;
        }
        return shortObject.shortValue();
    }

    public static Integer toInteger(final Object obj) {
        Number answer = toNumber(obj);
        if (answer == null) {
            return null;
        } else if (answer instanceof Integer) {
            return (Integer) answer;
        }
        return Integer.valueOf(answer.intValue());
    }

    public static Integer toInteger(final Object obj, Integer defaultValue) {
        Integer answer = toInteger(obj);
        if (answer == null) {
            answer = defaultValue;
        }
        return answer;
    }

    public static int toIntValue(final Object obj) {
        Integer integerObject = toInteger(obj);
        if (integerObject == null) {
            return 0;
        }
        return integerObject.intValue();
    }

    public static int toIntValue(final Object obj, int defaultValue) {
        Integer integerObject = toInteger(obj);
        if (integerObject == null) {
            return defaultValue;
        }
        return integerObject.intValue();
    }

    public static Long toLong(final Object obj) {
        Number answer = toNumber(obj);
        if (answer == null) {
            return null;
        } else if (answer instanceof Long) {
            return (Long) answer;
        }
        return Long.valueOf(answer.longValue());
    }

    public static Long toLong(final Object obj, Long defaultValue) {
        Long answer = toLong(obj);
        if (answer == null) {
            answer = defaultValue;
        }
        return answer;
    }

    public static long toLongValue(final Object obj) {
        Long longObject = toLong(obj);
        if (longObject == null) {
            return 0L;
        }
        return longObject.longValue();
    }

    public static long toLongValue(final Object obj, long defaultValue) {
        Long longObject = toLong(obj);
        if (longObject == null) {
            return defaultValue;
        }
        return longObject.longValue();
    }

    public static Float toFloat(final Object obj) {
        Number answer = toNumber(obj);
        if (answer == null) {
            return null;
        } else if (answer instanceof Float) {
            return (Float) answer;
        }
        return Float.valueOf(answer.floatValue());
    }

    public static Float toFloat(final Object obj, Float defaultValue) {
        Float answer = toFloat(obj);
        if (answer == null) {
            answer = defaultValue;
        }
        return answer;
    }

    public static float toFloatValue(final Object obj) {
        Float floatObject = toFloat(obj);
        if (floatObject == null) {
            return 0f;
        }
        return floatObject.floatValue();
    }

    public static float toFloatValue(final Object obj, float defaultValue) {
        Float floatObject = toFloat(obj);
        if (floatObject == null) {
            return defaultValue;
        }
        return floatObject.floatValue();
    }

    public static Double toDouble(final Object obj) {
        Number answer = toNumber(obj);
        if (answer == null) {
            return null;
        } else if (answer instanceof Double) {
            return (Double) answer;
        }
        return Double.valueOf(answer.doubleValue());
    }

    public static Double toDouble(final Object obj, Double defaultValue) {
        Double answer = toDouble(obj);
        if (answer == null) {
            answer = defaultValue;
        }
        return answer;
    }

    public static double toDoubleValue(final Object obj) {
        Double doubleObject = toDouble(obj);
        if (doubleObject == null) {
            return 0d;
        }
        return doubleObject.doubleValue();
    }

    public static double toDoubleValue(final Object obj, double defaultValue) {
        Double doubleObject = toDouble(obj);
        if (doubleObject == null) {
            return defaultValue;
        }
        return doubleObject.doubleValue();
    }

    public static BigInteger toBigInteger(final Object obj) {
        Long longObject = toLong(obj);
        if (longObject == null) {
            return BigInteger.ZERO;
        }
        return BigInteger.valueOf(longObject.longValue());
    }

    public static BigInteger toBigInteger(final Object obj, BigInteger defaultValue) {
        Long longObject = toLong(obj);
        if (longObject == null) {
            return defaultValue;
        }
        return BigInteger.valueOf(longObject.longValue());
    }

    public static BigDecimal toBigDecimal(final Object obj) {
        Double doubleObject = toDouble(obj);
        if (doubleObject == null) {
            return BigDecimal.ZERO;
        }
        return BigDecimal.valueOf(doubleObject.doubleValue());
    }

    public static BigDecimal toBigDecimal(final Object obj, BigDecimal defaultValue) {
        Double doubleObject = toDouble(obj);
        if (doubleObject == null) {
            return defaultValue;
        }
        return BigDecimal.valueOf(doubleObject.doubleValue());
    }

    @SuppressWarnings("unchecked")
    public static <R> R cast(final Object obj, final Class<R> clz) {
        R result = null;
        if (Boolean.class.equals(clz) || boolean.class.equals(clz)) {
            result = (R) toBoolean(obj);
        } else if (Byte.class.equals(clz) || byte.class.equals(clz)) {
            result = (R) toByte(obj);
        } else if (Short.class.equals(clz) || short.class.equals(clz)) {
            result = (R) toShort(obj);
        } else if (Integer.class.equals(clz) || int.class.equals(clz)) {
            result = (R) toInteger(obj);
        } else if (Long.class.equals(clz) || long.class.equals(clz)) {
            result = (R) toLong(obj);
        } else if (Float.class.equals(clz) || float.class.equals(clz)) {
            result = (R) toFloat(obj);
        } else if (Double.class.equals(clz) || double.class.equals(clz)) {
            result = (R) toDouble(obj);
        } else if (BigInteger.class.equals(clz)) {
            result = (R) toBigInteger(obj);
        } else if (BigDecimal.class.equals(clz)) {
            result = (R) toBigDecimal(obj);
        } else if (String.class.equals(clz)) {
            result = (R) toString(obj);
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    public static <R> R cast(final Object obj, R defaultValue) {
        R result = null;
        if (defaultValue == null) {
            return result;
        }
        Class<?> clz = defaultValue.getClass();
        if (Boolean.class.equals(clz) || boolean.class.equals(clz)) {
            result = (R) toBoolean(obj, (Boolean) defaultValue);
        } else if (Byte.class.equals(clz) || byte.class.equals(clz)) {
            result = (R) toByte(obj, (Byte) defaultValue);
        } else if (Short.class.equals(clz) || short.class.equals(clz)) {
            result = (R) toShort(obj, (Short) defaultValue);
        } else if (Integer.class.equals(clz) || int.class.equals(clz)) {
            result = (R) toInteger(obj, (Integer) defaultValue);
        } else if (Long.class.equals(clz) || long.class.equals(clz)) {
            result = (R) toLong(obj, (Long) defaultValue);
        } else if (Float.class.equals(clz) || float.class.equals(clz)) {
            result = (R) toFloat(obj, (Float) defaultValue);
        } else if (Double.class.equals(clz) || double.class.equals(clz)) {
            result = (R) toDouble(obj, (Double) defaultValue);
        } else if (BigInteger.class.equals(clz)) {
            result = (R) toBigInteger(obj, (BigInteger) defaultValue);
        } else if (BigDecimal.class.equals(clz)) {
            result = (R) toBigDecimal(obj, (BigDecimal) defaultValue);
        } else if (String.class.equals(clz)) {
            result = (R) toString(obj, (String) defaultValue);
        }
        return result;
    }

    public static boolean isDataNull(Object object) {
        return object == null || object.toString().isEmpty();
    }
}
